﻿namespace DependencyPropertyChangedSample.Extensions
{
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;

    /// <summary>
    /// Class to help animations from code using the CompositeTransform
    /// </summary>
    public static class FrameworkElementExtensions
    {
        /// <summary>
        /// Finds the composite transform either direct
        /// or as part of a TransformGroup
        /// </summary>
        /// <param name="fe">FrameworkElement</param>
        /// <returns></returns>
        public static CompositeTransform GetCompositeTransform(this FrameworkElement fe)
        {
            if (fe.RenderTransform != null)
            {
                var tt = fe.RenderTransform as CompositeTransform;
                if( tt != null) return tt;

                var tg = fe.RenderTransform as TransformGroup;
                if (tg != null)
                {
                    return tg.Children.OfType<CompositeTransform>().FirstOrDefault();
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the point to where FrameworkElement is translated
        /// </summary>
        /// <param name="fe">FrameworkElement</param>
        /// <returns>Translation point</returns>
        public static Point GetTranslatePoint(this FrameworkElement fe)
        {
            var translate = fe.GetCompositeTransform();
            if (translate == null) throw new ArgumentNullException("CompositeTransform");

            return new Point(
                (double)translate.GetValue(CompositeTransform.TranslateXProperty),
                (double)translate.GetValue(CompositeTransform.TranslateYProperty));

        }


        /// <summary>
        /// Gets the point to where FrameworkElement is located in a Canvas
        /// </summary>
        /// <param name="element">UIElement</param>
        /// <returns>Location point</returns>
        public static Point GetCanvasPoint(this UIElement element)
        {
            return new Point(
                x: Canvas.GetLeft(element),
                y: Canvas.GetTop(element)
            );
        }

        /// <summary>
        /// Locates a FrameworkElement to a new location in a Canvas
        /// </summary>
        /// <param name="element">UIElement</param>
        /// <param name="p">the new location</param>
        public static void SetCanvasPoint(this UIElement element, Point p)
        {
            SetCanvasPoint(element, p.X, p.Y);
        }

        /// <summary>
        /// Locates a FrameworkElement to a new location in a Canvas
        /// </summary>
        /// <param name="fe">UIElement</param>
        /// <param name="x">X coordinate of the new location</param>
        /// <param name="y">Ycoordinate of the new location</param>
        public static void SetCanvasPoint(this UIElement element, double x, double y)
        {
            Canvas.SetLeft(element, x);
            Canvas.SetTop(element, y);
        }

        /// <summary>
        /// Translates a FrameworkElement to a new location
        /// </summary>
        /// <param name="fe">FrameworkElement</param>
        /// <param name="p">the new location</param>
        public static void SetTranslatePoint(this FrameworkElement fe, Point p)
        {
            var translate = fe.GetCompositeTransform();
            if (translate == null) throw new ArgumentNullException("CompositeTransform");

            translate.SetValue(CompositeTransform.TranslateXProperty, p.X);
            translate.SetValue(CompositeTransform.TranslateYProperty, p.Y);
        }

        /// <summary>
        /// Translates a FrameworkElement to a new location
        /// </summary>
        /// <param name="fe">FrameworkElement</param>
        /// <param name="x">X coordinate of the new location</param>
        /// <param name="y">Ycoordinate of the new location</param>
        public static void SetTranslatePoint(this FrameworkElement fe, double x, double y)
        {
            fe.SetTranslatePoint(new Point(x, y));
        }

        public static FrameworkElement GetElementToAnimate( this FrameworkElement fe)
        {
            var parent = fe.GetVisualParent();
            return parent is ContentPresenter ? parent : fe;
        }
    }
}
